-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[charts] Support animation #9926
Conversation
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
Deploy preview: https://deploy-preview-9926--material-ui-x.netlify.app/ Updated pages: |
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
@@ -117,12 +124,28 @@ export function BarElement(props: BarElementProps) { | |||
}; | |||
const classes = useUtilityClasses(ownerState); | |||
|
|||
const spring = useSpring({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know if our competitors are bundling a third party animation library like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Nivo is using spring
- Rechart is using react-transition-group -> sounds limited for animating props modification
- Echarts has its own set of function -> mAybe to much work for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
One advantage of react-transition-group
is that we already bundle it for the pickers so most users will have it in their bundle anyway.
But if it's too limited, I agree that going for react-spring
can be interesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From What I understand, react-transition-group is mostly to create transition during the creation/deletion of components. But here we will also be interested in props modification. For example adding a bar means pushing all the other ones to a new position
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW in my last projects I've always been using this minimalistic animation function, I was very satisfied with the choice because it's very simple to understand & tune. Adding a wrapper around it to make it into a hook should be trivial.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spend some time to think about it, but will go with react-spring for now, more for their animated
elements than for the interpolation functions. It allows to pass style as usual without having react re-render
https://www.react-spring.dev/docs/concepts/animated-elements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nice addition and with a very little amount of new code.
If we agree to use react-spring
(cc @LukasTy), then for me the only thing missing is a prop to disable the animation (because that's clearly something not everybody wants.
And disable it on the sparkline.
@@ -64,6 +65,7 @@ export const BarElementPath = styled('rect', { | |||
export type BarElementProps = Omit<BarElementOwnerState, 'isFaded' | 'isHighlighted'> & | |||
React.ComponentPropsWithoutRef<'path'> & { | |||
highlightScope?: Partial<HighlightScope>; | |||
yOrigine: number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/yOrigine/yOrigin/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might admit I do not understand this comment 🙈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signed-off-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
const { series, stackingGroups } = seriesData; | ||
const { xAxis, yAxis, xAxisIds, yAxisIds } = axisData; | ||
const defaultXAxisId = xAxisIds[0]; | ||
const defaultYAxisId = yAxisIds[0]; | ||
|
||
const data = stackingGroups.flatMap(({ ids: groupIds }, groupIndex) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That can seem to be a huge modification, but it's "just" moving the computation of rectangle position at the top such that those coordinates can be passed to the useTransition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing addition 🎉 💙
About the animation starting at (0, 0) point, I confirm it get fixed by modifying the responsive container as follows. The idea being that if we have no width/height it's useless to do the upcoming computation since we will need to do them back for the next render when we get access to the correct sizing of the component. <ResizableContainer ref={containerRef} ownerState={{ width: inWidth, height: inHeight }}>
+ {width && height ? (
<ChartContainer {...other} width={width} height={height} ref={ref} />
+ ) : null}
</ResizableContainer> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The solution looks very elegant. 👍
One concern worth taking note of is that this additional library is currently 1/3 of the whole charts package in size. 🙈
General question:
- Have you considered having the animation toggle top level (on the container), because I imagine that eventually we'll animate everything, even the tooltip movement. 🤔
- Consider having a default for
disableAnimation
oranimate
, which would respect theprefers-reduced-motion
os setting.
Similar to how we handlereduceAnimations
on pickers. - Providing animation customization is probably a separate issue and planned for the future?
- Have you looked over the argos differences? Some of those seem concerning and the result new doc page actually has overflowing bars. 🤔
Yes, but it allows us to move forward. Maybe removing it for a lighter solution when we get a large userbase.
Good idea, but I'm not sure it's worth it.
Not really. In the issue, someone said that they just use default animation. We could consider providing a way to customize react-spring configuration, to get faster/slower animation. But more advanced customization seems to be a path in a difficult problem for no reward.
What do you mean by "overflowing"? For this kind of diff, the SVG edges definition is quite vague about how they are computed. So I assume that modifying the CPU usage can lead to edge errors. |
Co-authored-by: Nora <72460825+noraleonte@users.noreply.github.com> Co-authored-by: Lukas <llukas.tyla@gmail.com> Signed-off-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
The latest Argos changes seem strange... As if the explicit |
Yes, Argos use global settings and I modified the hook such that it removes animation for users with a11y issue but do nothing otherwise |
It works :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! 💯
The precision question can be addressed separately. 👍
The current solution is to use
react-spring
transition.To let Argos pass, I added a config that disabled the animation.
The demonstration: https://deploy-preview-9926--material-ui-x.netlify.app/x/react-charts/bars/#animation
It still suffers a small bug
In responsive mode, bars seem to come from the point (0, 0) instead of just growing from bottom to top.
It's because in responsive mode, the width of the chart is computed from its parent in a
useEffect
. So before theuseEffect
is done, the chart width is set by default to 0.So from the point of view of
useTransition
the initial point is (0, 0) whereas it should be the correct one withheight
set to 0.I think I will just block children's rendering at the first rendering in responsive. But if you have a better idea